/**
 * Copyright 2019 吉鼎科技.

 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package cn.easyplatform.util;

import cn.easyplatform.contexts.RecordContext;
import cn.easyplatform.dos.FieldDo;
import cn.easyplatform.dos.Record;
import cn.easyplatform.dos.UserDo;
import cn.easyplatform.entities.beans.LogicBean;
import cn.easyplatform.i18n.I18N;
import cn.easyplatform.interceptor.CommandContext;
import cn.easyplatform.lang.Strings;
import cn.easyplatform.messages.response.SimpleResponseMessage;
import cn.easyplatform.services.IProjectService;
import cn.easyplatform.services.ISubject;
import cn.easyplatform.type.FieldType;
import cn.easyplatform.type.IResponseMessage;
import cn.easyplatform.type.UserType;
import cn.easyplatform.utils.HttpUtil;
import org.apache.shiro.SecurityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;

/**
 * @author <a href="mailto:davidchen@epclouds.com">littleDog</a> <br/>
 * @since 2.0.0 <br/>
 */
public final class WxUtil {

    private final static Logger log = LoggerFactory.getLogger(WxUtil.class);

    public static IResponseMessage<?> quick(CommandContext cc, IProjectService projectservice, String type, String wxcode, String ip) {
        Map<String, String> options = projectservice.getConfig().getOptions(type);
        if (options == null)
            return new SimpleResponseMessage("wx01", I18N.getLabel("easyplatform.config.not.found", type));
        if (Strings.isBlank(options.get("entity")))
            return new SimpleResponseMessage("wx01", I18N.getLabel("easyplatform.config.not.found", "logic"));
        Object rs;
        if (type.contains("min"))//小程序
            rs = doWxMin(wxcode, options);
        else //公众号
            rs = doWxPub(wxcode, options);
        if (rs instanceof String)
            return new SimpleResponseMessage("wx02", rs);
        else {
            LogicBean logic = cc.getEntity(options.get("entity"));
            if (logic == null)
                return new SimpleResponseMessage("wx03", I18N.getLabel("easyplatform.config.not.found", "logic"));
            Map<String, Object> json = (Map<String, Object>) rs;
            UserDo guest = RuntimeUtils.createGustUser("oauth", UserType.TYPE_OAUTH, cc.getEnv(), projectservice);
            guest.setIp(ip);
            guest.setId((String) json.get("openid"));
            cc.setUser(guest);
            //初始环境，执行逻辑
            Map<String, Object> systemVariables = new HashMap<String, Object>();
            RuntimeUtils.initWorkflow(systemVariables, null);
            RecordContext rc = new RecordContext(new Record(), systemVariables, new HashMap<>());
            //设置小程序来源类型
            rc.setVariable(new FieldDo("authType", FieldType.VARCHAR, type));
            rc.setVariable(new FieldDo("openid", FieldType.VARCHAR, guest.getId()));
            rc.setVariable(new FieldDo("ipAddress", FieldType.VARCHAR, ip));
            try {
                cc.beginTx();
                String code = RuntimeUtils.eval(cc, logic, rc);
                if (!code.equals("0000")) {
                    cc.rollbackTx();
                    return MessageUtils.byErrorCode(cc, rc, null, code);
                }
                cc.commitTx();
            } catch (Exception e) {
                cc.rollbackTx();
                return MessageUtils.getMessage(e, log);
            } finally {
                cc.closeTx();
            }
            Object registered = cc.remove("$passport");
            return new SimpleResponseMessage(registered);
        }
    }

    /**
     * 验证码登陆
     *
     * @param cc
     * @param projectservice
     * @param phone
     * @param code
     * @param ip
     * @return
     */
    public static IResponseMessage<?> phone(CommandContext cc, IProjectService projectservice, String phone, String code, String ip) {
        Map<String, String> options = projectservice.getConfig().getOptions("phone");
        if (options == null)
            return new SimpleResponseMessage("wx01", I18N.getLabel("easyplatform.config.not.found", "phone"));
        if (Strings.isBlank(options.get("entity")))
            return new SimpleResponseMessage("wx01", I18N.getLabel("easyplatform.config.not.found", "logic"));
        LogicBean logic = cc.getEntity(options.get("entity"));
        if (logic == null)
            return new SimpleResponseMessage("wx03", I18N.getLabel("easyplatform.config.not.found", "logic"));
        UserDo guest = RuntimeUtils.createGustUser("oauth", UserType.TYPE_OAUTH, cc.getEnv(), projectservice);
        guest.setIp(ip);
        guest.setId(phone);
        cc.setUser(guest);
        //初始环境，执行逻辑
        Map<String, Object> systemVariables = new HashMap<String, Object>();
        RuntimeUtils.initWorkflow(systemVariables, null);
        RecordContext rc = new RecordContext(new Record(), systemVariables, new HashMap<>());
        //设置小程序来源类型
        rc.setVariable(new FieldDo("authType", FieldType.VARCHAR, "phone"));
        rc.setVariable(new FieldDo("code", FieldType.VARCHAR, code));
        rc.setVariable(new FieldDo("ipAddress", FieldType.VARCHAR, ip));
        try {
            cc.beginTx();
            String rs = RuntimeUtils.eval(cc, logic, rc);
            if (!rs.equals("0000")) {
                cc.rollbackTx();
                return MessageUtils.byErrorCode(cc, rc, null, rs);
            }
            cc.commitTx();
        } catch (Exception e) {
            cc.rollbackTx();
            return MessageUtils.getMessage(e, log);
        } finally {
            cc.closeTx();
        }
        Object registered = cc.remove("$passport");
        return new SimpleResponseMessage(registered);
    }

    /**
     * 微信小程序登陆
     *
     * @param code
     * @param options
     * @return
     */
    public static Object doWxPub(String code, Map<String, String> options) {
        try {
            Map<String, Object> resp = (Map<String, Object>) HttpUtil.get(String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", options.get("appid"), options.get("appsecret"), code));
            if (log.isInfoEnabled())
                log.info("doWxPub {} - {}", code, resp);
            if (resp == null)
                return I18N.getLabel("api.call.error", "wxlogin");
            if (resp.get("openid") != null)
                return resp;
            else
                return resp.get("errcode") + ":" + resp.get("errmsg");
        } catch (Exception e) {
            if (log.isErrorEnabled())
                log.error("doWxPub", e);
            return e.getMessage();
        }
    }

    /**
     * 微信小程序登陆
     *
     * @param code
     * @param options
     * @return
     */
    public static Object doWxMin(String code, Map<String, String> options) {
        try {
            Map<String, Object> resp = (Map<String, Object>) HttpUtil.get(String.format("https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code", options.get("appid"), options.get("appsecret"), code));
            if (log.isInfoEnabled())
                log.info("doWxMin {} - {}", code, resp);
            if (resp == null)
                return I18N.getLabel("api.call.error", "wxlogin");
            if (resp.get("openid") != null)
                return resp;
            else
                return resp.get("errcode") + ":" + resp.get("errmsg");
        } catch (Exception e) {
            if (log.isErrorEnabled())
                log.error("doWxMin", e);
            return e.getMessage();
        }
    }
}
